/***********************************************************************
 * Module:  Group.java
 * Author:  juny
 * Created: 2006年7月13日 13:58:52
 * Purpose: Defines the Class Group
 ***********************************************************************/

package com.powerunion.datacollection.report.excelreport.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.powerunion.datacollection.report.excelreport.base.BaseBand;
import com.powerunion.datacollection.report.excelreport.base.ITempletContainer;
import com.powerunion.datacollection.report.excelreport.base.Parameter;
import com.powerunion.datacollection.report.excelreport.base.element.FieldVariable;
import com.powerunion.datacollection.report.excelreport.config.ReportConfig.GroupConfig;
import com.powerunion.datacollection.report.excelreport.datasource.IDataSource;
import com.powerunion.datacollection.report.excelreport.util.AnalyseTempletTool;

/**
 * 
 * @author juny
 */
public class Group extends BaseBand
{
    /**
     * @param container
     */
    public Group(ITempletContainer container) {
        super(container);
        this.oldValues = new HashMap();
    }

    /*
     * @see excel.report.util.IElementWriter#setElementTempletValue(java.lang.String)
     */
    public void setElementTempletValue(String value) {
        String name = AnalyseTempletTool.getPorperty(
                						value, 
                						AnalyseTempletTool.PROPERTY_NAME
                	  );
        dsName = AnalyseTempletTool.getPorperty(
        		value,
        		AnalyseTempletTool.PROPERTY_DATASOURCE
        	);
        this.setName(name);
        setHearder();
    }
    
    /*
     * 输出一个组数据，判断数据是否是属于一组是根据分组字段值是否相等来判断的，
     * 在不同记录间分组字段值相等的记录都属于同一组，
     * 注意：记录集在进行分组前必须已经按分组字段依次排序过。
     * (non-Javadoc)
     * @see net.excel.report.base.IElementWriter#write(net.excel.report.base.Parameter)
     */
    public boolean write(Parameter param) throws Exception{
        IDataSource ds = getGourpDataSource(param);
        //记录写数据时的开始行
        this.realBeginRow = param.curRow;
        
        //打印新组的组头信息
        if(isNewGroup(param, true)){
            this.writeHead(param);
        }
        
        int bodyBegin = param.curRow;
        if(ds.size()>0){
            do{
		        this.writeBody(param);
		        ds.next();
		        //判断下一组数据是否属于同一组，不是则终止组的数据输出
		        if(isNewGroup(param, false)){
		            //把数据源返回到预读的一条记录
		            ds.undoNext();
	                break;
	            }
            }while(ds.hasNext());
        }
        
        int bodyEnd = param.curRow - 1;
        if(bodyBegin < bodyEnd){
        	if(null != this.getProperty()){
        		this.mergeColumn(bodyBegin, bodyEnd, param);
        	}
        }
        
        this.writeFoot(param);
        
        //记录写入数据的总行数
        this.realRowCount = param.curRow - this.realBeginRow;
        return true;
    }
    
    private IDataSource dataSource = null;
    private IDataSource getGourpDataSource(Parameter param){
        if(null == dataSource){
            dataSource = (IDataSource)param.dataSources.get(dsName);
        }
        return dataSource;
    }
    
    private boolean isNewGroup(Parameter param, boolean replaceOldValue) throws Exception{
        if(null == groupby){
            groupby = new ArrayList();
            iniGroupFields(param);
        }
        
        Object oValue = null;
        FieldVariable field = null;
        boolean bNotEqual = false;
        for(int i=0; i<groupby.size(); i++){
            field = (FieldVariable)groupby.get(i);
            oValue = this.oldValues.get(field.getName());
            if(null == oValue || !oValue.equals(field.getValue())){
                if(replaceOldValue){
                    oldValues.put(field.getName(), field.getValue());
                }
                bNotEqual = true;
            }
        }
        
        return bNotEqual;
    }
    
    private void iniGroupFields(Parameter param) throws Exception{
        GroupConfig groupConfig = sheetConfig.getGroupConfig(this.getName());
        if(null == groupConfig){
            throw new Exception("Couldn't get the group config information! group=" + getName()
                    	+ " \nPlease confirm you have defined the right group config infomation in the config file.");
        }
        
        /*String dsName = groupConfig.getDsName();
        if(dsName.equals("")){
            throw new Exception("Couldn't get the dataSource config information! group=" + getName());
        }*/
        
        String[] fields = groupConfig.getGroupByFields();
        //added by ajun 2006-11-10 如果在模板文件中没有配置分组数据源信息，则从配置文件取得
        //分组对应的数据源名称
        if(null == dsName || "".equals(dsName)){
            dsName = groupConfig.getDsName();
        }
        if(null == dsName || "".equals(dsName)){
            throw new Exception("You should specify the datasource name for goup [" + groupConfig.getName() + "]");
        }
        
        FieldVariable field = null;
        if(null != fields){
            for(int i=0; i<fields.length; i++){
	            field = new FieldVariable(dsName + AnalyseTempletTool.DATASOURCE_FIELD_SEPARATOR + fields[i]);
	            field.setDataSource(param.dataSources);
	            groupby.add(field);
            }
        }
    }

    private List groupby = null;
    private Map oldValues = null;
    private String dsName = null;
}